package domain;

import common.DomainException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

public final class Architecture {

    private Map<String, Layer> layerMap;
    private String name;
    private String author;

    protected Architecture() {
        this.layerMap = new LinkedHashMap<String, Layer>();
    }

    protected void addLayer(String name, int number) throws DomainException {
        if (!layerMap.containsKey(name)) {
            layerMap.put(name, new Layer(name, number));
        } else {
            throw new DomainException("Layer name already exists.");
        }
    }
    
    protected void addAllowedLayerToLayer(String fromLayer, String toLayer) throws DomainException{
        if (this.getLayerMap().containsKey(fromLayer)) {
            Layer fromLayerObject = this.getLayerMap().get(fromLayer);
            Layer toLayerObject = null;
            if (this.getLayerMap().containsKey(toLayer)) {
                toLayerObject = this.getLayerMap().get(toLayer);
                fromLayerObject.addAllowedLayer(toLayerObject);
            } else {
                throw new DomainException("The layer that you want to add as a allowed layer doesn't exist!");
            }
        } else {
            throw new DomainException("Couldn't add a layer to a non-existant layer.");
        }
    }
    
    protected Map<String, Layer> getAllowedLayersForLayer(String layer) throws DomainException {
        Map<String, Layer> allowedLayers = new HashMap<String, Layer>();

        if (this.getLayerMap().containsKey(layer)) {
            allowedLayers = this.getLayerMap().get(layer).getAllowedLayers();
        } else {
            throw new DomainException("The layer you have selected doesn't exist");
        }

        return allowedLayers;
    }
    
    protected void removeAllowedLayerForLayer(String deleteLayer, String fromLayer) throws DomainException {
        if (this.getLayerMap().containsKey(fromLayer)) {
            Layer layer = this.getLayerMap().get(fromLayer);
            layer.removeAllowedLayer(deleteLayer);
        } else {
            throw new DomainException("The layer you want to delete from doesn't exist.");
        }
    }
    
    protected void addUnitToLayer(String unitName, String type, String layerName) throws DomainException {
        Layer layer = this.getLayerMap().get(layerName);
        if(layer != null)
        {
            layer.addUnit(new Unit(unitName, UnitType.valueOf(type)));
        }
    }
    
    protected void removeUnitFromLayer(String unitName, String unitType, String layerName) {
        Layer layer = this.getLayerMap().get(layerName);
        if(layer != null){
            layer.removeUnitByUnitName(unitName, unitType);
        }
    }
    
    public Set<Unit> getUnitsForLayer(String layerName) throws DomainException {
        Set<Unit> unitsForLayer = new HashSet<Unit>();

        if (this.getLayerMap().containsKey(layerName)) {
            Layer layer = this.getLayerMap().get(layerName);
            if(layer != null)
            {
                unitsForLayer = layer.getUnits();
            }
        } else {
            throw new DomainException("That layer doesn't exist!");
        }

        return unitsForLayer;
    }

    protected void removeLayer(String layerName) {
        if (layerMap.containsKey(layerName)) {
            layerMap.remove(layerName);
        }
        
    }

    public Map<String, Layer> getLayerMap() {
        return layerMap;
    }

    protected void setLayerMap(Map<String, Layer> layerMap) {
        this.layerMap = layerMap;
    }

    public String getName() {
        return name;
    }

    protected void setName(String name) throws DomainException {
        if (!name.equals("")) {
            this.name = name;
        }
    }

    public String getAuthor() {
        return author;
    }

    protected void setAuthor(String author) throws DomainException {
        if (!author.equals("")) {
            this.author = author;
        }
    }
}
